#include <thread>
#include <queue>
#include <iostream>
#include <vector>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <unistd.h>
#include <string>
/*****************
 *         手撕线程池
 * ********************* */

const int gsize = 5;

template <class T>
class ThreadPool
{
public:
    static ThreadPool<T>* GetInstanc(){
        if(!instance)
        {
            std::unique_lock<std::mutex> lock(ThreadPool<T>::Mtx);
            {
                if(instance==nullptr){
                    std::cout<<"创建单例"<<std::endl;
                    instance=new ThreadPool<T>();
                }
            }
        }
        return instance;
    }

    void Start()
    {
        // for (int i = 0; i < _capacity; i++)
        // {
        //     _threads[i] = std::thread(ThreadPool::ThreadRoutinue, this,"thread-"+std::to_string(i));
        // }

        for (int i = 0; i < _capacity; i++)
        {
            _threads[i] = std::thread([this, i]()
                                      { ThreadRoutinue("thread-" + std::to_string(i)); });
        }
    }

    void Push(const T &in)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _q.push(in);
        }
        _cv.notify_one();
        std::cout << "放任务" << std::endl;
    }

    // static void ThreadRoutinue(ThreadPool *tp, const std::string name)
    // {
    //     while (true)
    //     {
    //         T t;
    //         {
    //             std::unique_lock<std::mutex> lock(tp->_mutex);
    //             while (tp->_q.empty())
    //             {
    //                 tp->_cv.wait(lock);
    //             }
    //             t = tp->_q.front();
    //             tp->_q.pop();
    //         }
    //         tp->_cv.notify_one();
    //         std::cout << "唤醒线程" << name << ":执行任务" << std::endl;
    //         t();
    //     }
    // }

    void ThreadRoutinue(const std::string name)
    {
        while (true)
        {
            T t;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                while (_q.empty())
                {
                    _cv.wait(lock);
                }
                t = _q.front();
                _q.pop();
            }
            _cv.notify_one();
            std::cout << "唤醒线程" << name << ":执行任务" << std::endl;
            t();
        }
    }

    ~ThreadPool()
    {
    }

private:    
    ThreadPool(int capacity = gsize)
        : _capacity(capacity)
    {
        _threads.resize(_capacity);
    }

    ThreadPool<T> operator=(const ThreadPool<T> &)=delete;
    ThreadPool operator()(const ThreadPool<T> &)=delete;

private:
    int _capacity;
    std::queue<T> _q;
    std::vector<std::thread> _threads;
    std::mutex _mutex;
    std::condition_variable _cv;

    static std::mutex Mtx;
    static ThreadPool *instance;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

template <class T>
std::mutex ThreadPool<T>::Mtx;

class Task
{
public:
    void Run()
    {
        std::cout << "hello linux!" << std::endl;
    }
    void operator()()
    {
        Run();
    }
};

int main()
{
    
    ThreadPool<Task>::GetInstanc()->Start();
    int cnt = 10;
    while (cnt--)
    {
        Task t;
        ThreadPool<Task>::GetInstanc()->Push(t);
        sleep(1);
    }
    return 0;
}